<?php
declare (strict_types = 1);

namespace app\tools;

use app\constant\auction\HouseConstant;
use app\constant\auction\SpiderConstant;
use app\facade\BaiDuFacade;
use app\facade\guzzle\ALiFaPaiRequestFacade;
use app\facade\guzzle\HaiTunRequestFacade;
use app\facade\HousesFacade;
use app\facade\StringFacade;
use app\facade\ZhiMaDaiLiFacade;
use app\model\communal\HousingModel;
use app\model\communal\RegionModel;
use Carbon\Carbon;
use Exception;
use QL\QueryList;

final class HousesTool
{
    /**
     * 根据参数获取省市区经纬度详细地址
     *
     * @param $params
     * @return mixed
     */
    public function getPositionByParams($params)
    {
        $longitude = $params['longitude'];
        $latitude = $params['latitude'];

        $result = [
            'longitude' => $longitude,
            'latitude' => $latitude,
            'address' => $params['address'],
            'province' => '',
            'province_code' => 0,
            'city' => '',
            'city_code' => 0,
            'district' => '',
            'code' => 0,
        ];

        if ((0 == $latitude || 0 == $longitude) && empty($params['name']) && empty($params['address'])) {
            return $result;
        }

        try {
            // 经纬度
            if (0 == $latitude || 0 == $longitude) {
                $position = empty($params['address']) ? BaiDuFacade::geocoding(['address' => $params['name']]) : BaiDuFacade::geocoding(['address' => $params['address']]);

                $longitude = $position['location']['lng'];
                $latitude = $position['location']['lat'];
            }

            $geocoding = BaiDuFacade::reverseGeocoding(['location' => $latitude . ',' . $longitude]);
            $province = $geocoding['addressComponent']['province'];
            $city = $geocoding['addressComponent']['city'];
            $district = $geocoding['addressComponent']['district'];

            // 区域代码
            $provinceCode = RegionModel::where('name', 'like', '%' . $province)->value('code');
            $cityCode = RegionModel::where('name', 'like', '%' . $city)
                ->where('p_code', $provinceCode)->value('code');
            $code = RegionModel::where('name', 'like', '%' . $district)
                ->where('p_code', $cityCode)->value('code');

            $temp['longitude'] = $longitude;
            $temp['latitude'] = $latitude;
            $temp['address'] = $geocoding['formatted_address'];
            $temp['province'] = $province;
            $temp['province_code'] = $provinceCode ?? 0;
            $temp['city'] = $city;
            $temp['city_code'] = $cityCode ?? 0;
            $temp['district'] = $district;
            $temp['code'] = $code ?? 0;
        } catch (Exception $e) {
            return $result;
        }

        return $temp;
    }

    /**
     * 根据开结时间获取拍卖状态
     *
     * @param $startAt
     * @param $endAt
     * @return int
     */
    public function getAuctionStateByTime($startAt, $endAt)
    {
        if ($startAt > Carbon::now()->timestamp) {
            $auctionState = 1;
        } else if ($endAt < Carbon::now()->timestamp) {
            $auctionState = 3;
        } else {
            $auctionState = 2;
        }
        return $auctionState;
    }

    /**
     * 通用后羿采集器数据处理
     *
     * @param $row
     * @param $thirdSource
     * @return array
     */
    public function houYiSpiderHandle($row, $thirdSource)
    {
        static $list = [];

        $temp = [
            'title' => $row['A'],
            'start_price' => StringFacade::WanToYuan($row['D']),
            'cash_deposit' => StringFacade::WanToYuan($row['E']),
            'assess_price' => StringFacade::WanToYuan($row['F']),
            'market_assess_price' => StringFacade::WanToYuan($row['G']),
            'start_at' => empty($row['H']) ? Carbon::now()->timestamp : strtotime($row['H']),
            'end_at' => empty($row['I']) ? Carbon::now()->addDays(7)->timestamp : strtotime($row['I']),
            'housing_type' => $row['M'] == '住宅' ? HouseConstant::SECONDARY_TYPE_ONE : HouseConstant::SECONDARY_TYPE_TWO,
            'housing_status' => $row['L'],
            'auction_times' => $row['K'],
            'position' => $row['J'],
            'introduce' => $row['O'],
            'proclamation' => $row['P'],
            'third_id' => $row['C'],
            'third_detail_url' => $row['B'],
            'third_source' => $thirdSource,
            'spider_type' => SpiderConstant::SPIDER_TYPE_HOU_YI,
            'is_sync' => 1,
        ];

        // 拍卖公告
        $ql = QueryList::html($row['P']);
        $proclamation = HousesFacade::aLiProclamation($ql);
        $temp['proclamation'] = $proclamation;

        $others = [
            'unit_price' => $row['Q'], // 单价
            'built_area' => $row['R'], // 建筑面积
            'floor' => $row['S'], // 楼层
        ];

        $tempPics = [];
        /*
         * 海豚选房特殊处理
         */
        if (SpiderConstant::THIRD_SOURCE_HAI_TUN == $thirdSource) {
            // 房源类型
            $temp['housing_type'] = $row['M'] == '住宅' ? HouseConstant::SECONDARY_TYPE_ONE : HouseConstant::SECONDARY_TYPE_THREE;

            // 图片
            $qlPics = QueryList::html($row['N']);
            $tempPics = $this->haiTunPicsHandle($qlPics);

            // 经纬度
            $isGeo = preg_match('/houseBasic.*geo:{x:(.*?),y:(.*?)},hs_pic_url/', $row['T'], $matches); // 经纬度
            $longitude = $isGeo ? $matches[1] : null; // longitude 经度
            $latitude = $isGeo ? $matches[2] : null; // latitude 纬度
            $others['longitude'] = $longitude;
            $others['latitude'] = $latitude;
        }

        /*
         * 阿里法拍特殊处理
         */
        if (SpiderConstant::THIRD_SOURCE_ALi == $thirdSource) {
            $temp['start_price'] = $row['D'];
            $temp['cash_deposit'] = $row['E'];
            $temp['assess_price'] = $row['F'];
            $temp['market_assess_price'] = $row['G'];

            // 拍卖开始时间/结束时间

            // // 通过代理获取列表页, 速度慢不稳定, 一直需要登录
            // // 参数
            // $params = StringFacade::convertUrlQuery($row['U']);
            // $listQl = $this->aLiQueryGet($row['U'], $params);
            // // 获取列表中
            // dd($listQl);

            // 图片
            $qlPics = QueryList::html($row['N']);
            $tempPics = $this->aLiPicsHandle($qlPics);

            // 经纬度
            if (empty($row['T'])) {
                $longitude = 0;
                $latitude = 0;
            } else {
                $coordinate = explode(',', $row['T']);
                $longitude = empty($coordinate) ? 0 : $coordinate[0];
                $latitude = empty($coordinate) ? 0 : $coordinate[1];
            }
            $others['longitude'] = $longitude;
            $others['latitude'] = $latitude;
        }

        $temp['pics'] = json_encode($tempPics, JSON_UNESCAPED_UNICODE);
        $temp['others'] = json_encode($others, JSON_UNESCAPED_UNICODE);

        return $temp;
    }

    /**
     * 通用房源数据处理
     *
     * @param $item
     * @return array[]
     */
    public function commonHousingHandle($item)
    {
        $others = empty($item['others']) ? [] : json_decode($item['others'], true);

        // 长度限制
        $mapParams = [
            'longitude' => isset($others['longitude']) ? $others['longitude'] : 0,
            'latitude' => isset($others['latitude']) ? $others['latitude'] : 0,
            'address' => isset($item['position']) && !empty($item['position']) ?  mb_substr($item['position'], 0, 50) : '',
            'name' => isset($item['title']) && !empty($item['title']) ? mb_substr($item['title'], 0, 50) : '',
        ];
        $position = HousesFacade::getPositionByParams($mapParams);

        $auctionTimes = $item['auction_times'];
        switch ($item['housing_status']) {
            case 2:
                $auctionTimes = '流拍';
                break;
            case 3:
                $auctionTimes = '已成交';
                break;
        }

        $startAt = !empty($item['start_at']) ? $item['start_at'] : Carbon::now()->addDays(-3)->timestamp;
        $endAt = !empty($item['end_at']) ? $item['end_at'] : Carbon::now()->addDays(3)->timestamp;
        $auctionState = HousesFacade::getAuctionStateByTime($item['start_at'], $item['end_at']);

        $primary = [
            'admin_id' => 0,
            'village_id' => 0,
            'name' => !empty($item['title']) ? $item['title'] : '',
            'start_price' => !empty($item['start_price']) ? $item['start_price']: 0,
            'assess_price' => !empty($item['assess_price']) ? $item['assess_price'] : 0,
            'discount' => StringFacade::discount($item['start_price'], $item['assess_price']),
            'market_assess_price' => !empty($item['market_assess_price']) ? $item['market_assess_price'] : 0,
            'cash_deposit' => !empty($item['cash_deposit']) ? $item['cash_deposit'] : 0,
            'trading_amount' => !empty($item['transaction_price']) ? $item['transaction_price'] : 0,
            'trading_at' => !empty($item['transaction_time']) ? $item['transaction_time'] : 0,
            'start_at' => $startAt,
            'end_at' => $endAt,
            'auction_state' => $auctionState,
            'auction_times' => in_array($auctionTimes, ['一拍','二拍','三拍','变卖','已成交','流拍']) ? HousingModel::$auctionTimesSpiderMap[$auctionTimes] : 99,
            'purpose' => $item['housing_type'],
            'occupy' => 0,
            'rent' => 0,
            'taxation' => 0,
            'address' => isset($position['address']) ? $position['address'] : '',
            'province' => isset($position['province']) ? $position['province'] : '',
            'province_code' => isset($position['province_code']) ? $position['province_code'] : 0,
            'city' => isset($position['city']) ? $position['city'] : '',
            'city_code' => isset($position['city_code']) ? $position['city_code'] : 0,
            'district' => isset($position['district']) ? $position['district'] : '',
            'code' => isset($position['code']) ? $position['code'] : 0,
            'longitude' => isset($position['longitude']) ? $position['longitude'] : 0,
            'latitude' => isset($position['latitude']) ? $position['latitude'] : 0,
            'built_area' => isset($others['built_area']) ? (int)str_replace('㎡', '', $others['built_area']) : 0,
            'third_source' => $item['third_source'],
        ];

        // 海豚选房 housing_type 特殊处理
        if (SpiderConstant::THIRD_SOURCE_HAI_TUN == $item['third_source']) {
            $housingTypeMap = [1 => 1, 2 => 2, 3 => 2];
            $primary['purpose'] = in_array($item['housing_type'], [1,2,3]) ? $housingTypeMap[$item['housing_type']] : 1;
        }

        // 附表数据拼装
        $sub = [
            'unit_price' => isset($others['unit_price']) ? $others['unit_price'] : 0,
            'floor' => isset($others['floor']) ? $others['floor'] : 0,
            'years' => '',
            'school' => '',
            'rail_transit' => '',
            'proclamation' => !empty($item['proclamation']) ? $item['proclamation']: '',
            'introduce' => !empty($item['introduce']) ? $item['introduce']: '',
            'enclosures' =>'',
            'video' => '',
            'video_poster' => '',
            'third_id' => $item['third_id'],
            'third_source' => $item['third_source'],
            'third_detail_url' => $item['third_detail_url'],
            'amis_location' => [
                'address' => isset($position['address']) ? $position['address'] : '',
                'lat' => isset($position['latitude']) ? $position['latitude'] : 0,
                'lng' => isset($position['longitude']) ? $position['longitude'] : 0,
                'city' => isset($position['city']) ? $position['city'] : '',
                'vendor' => 'baidu',
            ],
        ];

        // 图片处理
        if (!empty($item['pics'])) {
            $temp = [];
            $images = json_decode($item['pics'], true);
            foreach ($images as $image) {
                if (!is_null($image)) {
                    $temp[] = StringFacade::replaceOssShowUrl($image);
                }
            }
            $sub['images'] = implode(',', $temp);
        }

        return [
            'primary' => $primary,
            'sub' => $sub,
        ];
    }

    /**
     * 海豚法拍图片处理工具
     *
     * @param $ql
     * @return array
     */
    public function haiTunPicsHandle($ql)
    {
        $pics = $ql->find('.pic-list>li>img')->attrs('src')->toArray();
        // 处理图片
        $tempPics = [];
        if (!empty($pics)) {
            foreach ($pics as $pic) {
                $filename = HaiTunRequestFacade::downloadOss($pic, '/storage/haiTun/image');
                if (false == $filename) {
                    continue ;
                } else {
                    $tempPics[] = $filename;
                }
            }
        }

        return $tempPics;
    }

    /**
     * 阿里法拍图片处理工具
     *
     * @param $ql
     * @return array
     */
    public function aLiPicsHandle($ql)
    {
        $pics = $ql->find('.video-img>.sf-pic-slide>.slide-bigpic>img')->attrs('data-ks-lazyload')->toArray();
        // 下载图片
        $tempPics = [];
        if (!empty($pics) && empty($housingModel['images'])) {
            foreach ($pics as $pic) {
                $filename = ALiFaPaiRequestFacade::downloadOss('https:' . $pic, '/storage/ALiFaPai/image');
                if (false == $filename) {
                    continue ;
                } else {
                    $tempPics[] = $filename;
                }
            }
        }

        return $tempPics;
    }

    /**
     * 阿里法拍公告
     *
     * @param $ql
     * @return mixed
     */
    public function aLiProclamation($ql)
    {
        $proclamationUrl = 'https:' . $ql->find('#J_NoticeDetail')->attr('data-from');
        $proclamation = iconv('GBK','UTF-8',file_get_contents($proclamationUrl)); // 法拍公告
        $proclamation = str_replace('null(', '', trim($proclamation));
        $proclamation = json_decode(substr($proclamation, 0, strlen($proclamation) - 2), true);
        $proclamation = $proclamation['content'];
        return $proclamation;
    }

    /**
     * @param $url
     * @param $params
     * @return string|string[]
     * @throws Exception
     */
    public function aLiQueryGet($url, $params)
    {
        // 获取代理
        $proxy = ZhiMaDaiLiFacade::getSingleProxy();
        $pageQl = QueryList::get($url, $params, ['proxy' => $proxy, 'timeout' => 9, 'headers' => []])->getHtml();
        $pageQl = mb_convert_encoding($pageQl, 'UTF-8', 'GBK');
        $pageQl = str_replace('gbk', 'utf-8', $pageQl);

        // 中途可能出现登录页面
        if (strlen($pageQl) < 1600) {
            throw new Exception('阿里法拍登录检测');
        }

        return $pageQl;
    }
}
